/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MathLib.HashMatrix;

import java.util.ArrayList;

/**
 *
 * @author marko
 */
public class Gauss{
      // матрица
      private IMatrix matrix;
      // конструктор, принимает созданную матрицу коэффициентов
      public Gauss(IMatrix matrix){
            this.matrix = matrix;
      }
      // главный метод, возвращающий решение, принимает вектор свободных членов
      public double[] calculate(double[] B){
            // обнуляем нижнюю полуматрицу, перебирая сверху вниз все строки
            // и складывая каждую со всеми нижележащими
            for (int row=0; row<(matrix.getN()-1); row++){
                  // получаем все ненулевые значения обнуляемого столбца
                  ArrayList<Integer> colIndexes = matrix.getJColIndex(row);
                  ArrayList<Double> colValues = matrix.getJColValues(row);

                  // получаем индексы и значения ячеек строки, правее главной диагонали
                  // ячейки левее главной диагонали к этому моменту уже обнулены
                  ArrayList<Integer> rowIndexes = matrix.getJRowIndex(row);
                  ArrayList<Double> rowValues = matrix.getJRowValues(row);
                  // получаем элемент главной диагонали, которым будем обнулять столбец
                  double dd = matrix.getValue(row,row);
                  for (int i=0; i<colIndexes.size(); i++){
                     // высчитываем коэффициент
                     double k = colValues.get(i)/dd;
                     // k подобран таким образом чтобы обнулить ячейку столбца,
                     matrix.setValue(colIndexes.get(i),row,0);
                     // складываем строки
                     for (int ii=0; ii<rowIndexes.size(); ii++){
                        matrix.addValue(colIndexes.get(i),rowIndexes.get(ii),-rowValues.get(ii)*k);
                     }
                     // складываем соответствующие свободные члены
                     B[colIndexes.get(i)] -= B[row]*k;
                  }
            }
            // вектор невідомих
            double[] x = new double[matrix.getN()];
            // обернеий хід

            for (int row = (matrix.getN()-1); row>=0; row--){
               double e = 0;
               ArrayList<Integer> indexes = matrix.getJRowIndex(row);
               ArrayList<Double> values = matrix.getJRowValues(row);
               for (int i=0; i<indexes.size(); i++) e += x[indexes.get(i)]*values.get(i);
               x[row] = (B[row]-e)/matrix.getValue(row,row);
            }
            return x;
      }
}
